package com.sharesrc.jdev.wiimotedemo.views;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Level;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.apache.commons.io.FilenameUtils;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.JXTitledPanel;
import org.jdesktop.swingx.error.ErrorInfo;
import org.jdesktop.swingx.painter.MattePainter;
import org.wiigee.logic.Gesture;
import org.wiigee.logic.GestureModel;

import wiiusej.WiiUseApiManager;
import wiiusej.utils.AccelerationWiimoteEventPanel;
import wiiusej.utils.GForceWiimoteEventPanel;
import wiiusej.utils.OrientationWiimoteEventPanel;

import com.sharesrc.jdev.wiimotedemo.WiiUseJ;
import com.sharesrc.jdev.wiimotedemo.Wiigee;
import com.sharesrc.jdev.wiimotedemo.common.constant.Constants;
import com.sharesrc.jdev.wiimotedemo.common.constant.Themes;
import com.sharesrc.jdev.wiimotedemo.common.util.UIUtils;

import de.javasoft.swing.ButtonBar;
import de.javasoft.swing.JYSwitchButton;
import de.javasoft.swing.JYTabbedPane;
import de.javasoft.swing.JYTabbedPane.CloseButtonStrategy;
import de.javasoft.swing.plaf.jytabbedpane.Tab;

public class MainFrame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 201308131024L;

	JButton btnTraining, btnGesture, btnLibrary, btnEditGestureModelDisplayName, btnLoadGestureModel, btnSaveGestureModel;
	ButtonGroup btnGroup;
	AbstractButton btnConnect, btnDisconnect;
	JXTitledPanel contentTitledPanel;
	JPanel navigationPanel, contentPanel, trainingPanel, gestureRecognitionPanel, gestureModelsPanel;
	AccelerationWiimoteEventPanel accelerationPanel;
	OrientationWiimoteEventPanel orientationPanel;
	GForceWiimoteEventPanel gforcePanel;
	WiimotePanel wiimotePanel;
	JYSwitchButton sbMotionSensingTracking;
	JPanel trainingMonitorPanel;
	JLabel lblTrainingCountText, lblTrainingCount, lblTrainingMonitorStatus;
	JLabel lblGestureModelCountText, lblGestureModelCount;
	JList<String> listGestureModels;
	DefaultListModel<String> gestureModelsListModel;
	JLabel lblGestureRecognition;

	HashMap<String, GestureModelInfo> hmapGestureModels;

	ContentType currentContentType;

	WiiUseJ wiiusej = WiiUseJ.INSTANCE;
	Wiigee wiigee = Wiigee.INSTANCE;

	EventsHandler handler;

	public AccelerationWiimoteEventPanel getAccelerationPanel() {
		return this.accelerationPanel;
	}

	public OrientationWiimoteEventPanel getOrientationPanel() {
		return this.orientationPanel;
	}

	public GForceWiimoteEventPanel getGravityForcePanel() {
		return this.gforcePanel;
	}

	public WiimotePanel getWiimotePanel() {
		return this.wiimotePanel;
	}

	public MainFrame() {
		this.hmapGestureModels = new HashMap<String, GestureModelInfo>();
		this.handler = new EventsHandler();
		initUIComponents();

		Runtime.getRuntime().addShutdownHook(new Thread() {

			@Override
			public void run() {
				MainFrame.this.wiiusej.disconnectWiimote();
				WiiUseApiManager.definitiveShutdown();
			}
		});
	}

	private void createNavigationPanel() {
		this.navigationPanel = new JPanel();

		this.btnTraining = new JButton();
		this.btnTraining.setIcon(Constants.Images.TRAINING);
		this.btnTraining.setName("FlatButton");
		this.btnTraining.setToolTipText(Constants.Texts.TRAINING);
		this.btnTraining.addActionListener(this.handler);
		this.btnGesture = new JButton();
		this.btnGesture.setIcon(Constants.Images.GESTURE);
		this.btnGesture.setName("FlatButton");
		this.btnGesture.setToolTipText(Constants.Texts.GESTURE_RECOGNITION);
		this.btnGesture.addActionListener(this.handler);
		this.btnLibrary = new JButton();
		this.btnLibrary.setIcon(Constants.Images.LIBRARY);
		this.btnLibrary.setName("FlatButton");
		this.btnLibrary.setToolTipText(Constants.Texts.GESTURE_MODELS);
		this.btnLibrary.addActionListener(this.handler);

		UIUtils.addComponent(this.navigationPanel, this.btnTraining, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 40, 10, 0, 10, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, createLineDumpPanel(), GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, this.btnGesture, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 5, 10, 0, 10, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, createLineDumpPanel(), GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, this.btnLibrary, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 5, 10, 0, 10, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, createLineDumpPanel(), GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.navigationPanel, new JLabel(""), GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);
	}

	private void createContentPanel() {
		this.contentTitledPanel = new JXTitledPanel();
		this.contentTitledPanel.setTitleFont(Themes.Fuente.CONTENT_PANEL_TITLE);
		this.contentTitledPanel.setTitleForeground(Themes.Colore.CONTENT_PANEL_TITLE_FG);
		this.contentTitledPanel.setTitlePainter(new MattePainter(new GradientPaint(0, 0, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_1, 140, 140, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_2, true)));
		this.contentTitledPanel.setBorder(null);

		this.contentPanel = new JPanel();
		this.contentPanel.setOpaque(false);
		this.contentPanel.setLayout(new BorderLayout());
		this.contentPanel.setBorder(BorderFactory.createLoweredBevelBorder());

		this.contentTitledPanel.setContentContainer(this.contentPanel);
	}

	private JPanel createLineDumpPanel() {
		JPanel pnl = new JPanel();
		pnl.setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, Themes.Colore.LINE_DUMP));

		return pnl;
	}

	private void createGestureRecognitionPanel() {
		this.gestureRecognitionPanel = new JPanel();
		this.gestureRecognitionPanel.setBackground(Themes.Colore.CONTENT_PANEL_BG);

		JLabel lblIcon = new JLabel(Constants.Images.USER);
		this.lblGestureRecognition = new JLabel("");
		this.lblGestureRecognition.setOpaque(true);
		this.lblGestureRecognition.setHorizontalAlignment(JLabel.CENTER);
		this.lblGestureRecognition.setFont(Themes.Fuente.DEFAULT_HEADER_1);
		this.lblGestureRecognition.setForeground(Themes.Colore.TRAINING_MONITOR_STATUS_FG);
		this.lblGestureRecognition.setBackground(Themes.Colore.GESTURE_RECOGNITION_BG);
		this.lblGestureRecognition.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER), BorderFactory.createMatteBorder(5, 2, 5, 2, Themes.Colore.TRAINING_MONITOR_PANEL_BG)), BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER)));

		UIUtils.addComponent(this.gestureRecognitionPanel, lblIcon, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.BOTH, 50, 100, 30, 100, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.gestureRecognitionPanel, this.lblGestureRecognition, GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 30, 100, 50, 100, GridBagConstraints.CENTER);
	}

	private void createGestureModelsPanel() {
		this.gestureModelsPanel = new JPanel();
		this.gestureModelsPanel.setLayout(new BorderLayout());

		final JXTitledPanel gestureModelInfoTitledPanel = new JXTitledPanel();
		gestureModelInfoTitledPanel.setTitleFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		gestureModelInfoTitledPanel.setTitlePainter(new MattePainter(new GradientPaint(0, 0, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_1_ALT, 140, 140, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_2_ALT, true)));
		gestureModelInfoTitledPanel.setBorder(null);
		final JPanel gestureModelInfoPanel = new JPanel();
		gestureModelInfoPanel.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		gestureModelInfoPanel.setLayout(new BorderLayout());
		gestureModelInfoTitledPanel.setContentContainer(new JScrollPane(gestureModelInfoPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));

		this.gestureModelsListModel = new DefaultListModel<String>();
		this.listGestureModels = new JList<String>(this.gestureModelsListModel);
		this.listGestureModels.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		this.listGestureModels.addListSelectionListener(new ListSelectionListener() {

			@Override
			public void valueChanged(ListSelectionEvent e) {
				if (!e.getValueIsAdjusting()) {
					int selectedIndex = -1;
					if ((selectedIndex = MainFrame.this.listGestureModels.getSelectedIndex()) == -1) {
						return;
					}

					gestureModelInfoTitledPanel.setTitle(MainFrame.this.gestureModelsListModel.getElementAt(selectedIndex) + " > " + Constants.Texts.GESTURE_MODEL);

					gestureModelInfoPanel.removeAll();
					gestureModelInfoPanel.add(new GestureModelInfoPanel(MainFrame.this.hmapGestureModels.get(MainFrame.this.gestureModelsListModel.getElementAt(selectedIndex))), BorderLayout.CENTER);
					gestureModelInfoPanel.validate();
					gestureModelInfoPanel.repaint();
				}
			}
		});
		this.listGestureModels.setPreferredSize(new Dimension(320, this.listGestureModels.getPreferredSize().height));
		JScrollPane scrollPane = new JScrollPane(this.listGestureModels, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		scrollPane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER), BorderFactory.createMatteBorder(5, 2, 5, 2, Themes.Colore.CONTENT_PANEL_BG)), BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER)));

		JPanel footer = new JPanel();
		footer.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		this.lblGestureModelCountText = new JLabel(Constants.Texts.GESTURE_MODEL_COUNT);
		this.lblGestureModelCountText.setHorizontalAlignment(JLabel.LEADING);
		this.lblGestureModelCountText.setFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		this.lblGestureModelCountText.setForeground(Themes.Colore.TRAINING_MONITOR_COUNT_NUMBER_FG);
		this.lblGestureModelCountText.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 0));
		this.lblGestureModelCountText.addMouseListener(this.handler);
		this.lblGestureModelCount = new JLabel("0");
		this.lblGestureModelCount.setHorizontalAlignment(JLabel.LEADING);
		this.lblGestureModelCount.setFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		this.lblGestureModelCount.setForeground(Themes.Colore.TRAINING_MONITOR_STATUS_FG);
		this.lblGestureModelCount.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 0));
		this.lblGestureModelCount.addMouseListener(this.handler);

		JPanel pnlButtons = new JPanel();
		pnlButtons.setOpaque(false);
		pnlButtons.setLayout(new GridLayout(1, 3, 10, 0));
		this.btnEditGestureModelDisplayName = new JButton(Constants.Texts.EDIT);
		this.btnEditGestureModelDisplayName.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
		this.btnEditGestureModelDisplayName.addActionListener(this.handler);
		this.btnLoadGestureModel = new JButton(Constants.Texts.LOAD);
		this.btnLoadGestureModel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
		this.btnLoadGestureModel.addActionListener(this.handler);
		this.btnSaveGestureModel = new JButton(Constants.Texts.SAVE);
		this.btnSaveGestureModel.addActionListener(this.handler);
		pnlButtons.add(this.btnEditGestureModelDisplayName);
		pnlButtons.add(this.btnLoadGestureModel);
		pnlButtons.add(this.btnSaveGestureModel);

		UIUtils.addComponent(footer, this.lblGestureModelCountText, 1, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.LINE_START);
		UIUtils.addComponent(footer, this.lblGestureModelCount, 1, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.LINE_START);
		UIUtils.addComponent(footer, new JLabel(""), 1, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(footer, pnlButtons, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 10, 0, 10, 10, GridBagConstraints.LINE_END);

		this.gestureModelsPanel.add(scrollPane, BorderLayout.WEST);
		this.gestureModelsPanel.add(gestureModelInfoTitledPanel, BorderLayout.CENTER);
		this.gestureModelsPanel.add(footer, BorderLayout.SOUTH);
	}

	private void createTrainingPanel() {
		this.trainingPanel = new JPanel();

		final JYTabbedPane tabbedPane = new JYTabbedPane();
		tabbedPane.setOpaque(false);
		tabbedPane.setCloseButtonStrategy(CloseButtonStrategy.ALL_TABS);
		tabbedPane.getActionMap().put("closeTab", new AbstractAction() {

			/**
			 * 
			 */
			private static final long serialVersionUID = 201308141047L;

			@Override
			public void actionPerformed(ActionEvent e) {
				Tab tab = (Tab) SwingUtilities.getAncestorOfClass(Tab.class, (Component) e.getSource());
				if (tabbedPane.getTabCount() >= 2) {
					tabbedPane.removeTabAt(tab.getTabIndex());
					if (tabbedPane.getTabCount() == 1) {
						tabbedPane.setCloseButtonStrategy(CloseButtonStrategy.NONE);
					}
				}

			}
		});

		this.accelerationPanel = new AccelerationWiimoteEventPanel();
		this.orientationPanel = new OrientationWiimoteEventPanel();
		this.gforcePanel = new GForceWiimoteEventPanel();

		tabbedPane.add(Constants.Texts.ACCELERATION, this.accelerationPanel);
		tabbedPane.add(Constants.Texts.ORIENTATION, this.orientationPanel);
		tabbedPane.add(Constants.Texts.GRAVITY_FORCE, this.gforcePanel);

		tabbedPane.setIconAt(0, Constants.Images.ACCELERATION);
		tabbedPane.setIconAt(1, Constants.Images.ORIENTATION);
		tabbedPane.setIconAt(2, Constants.Images.GRAVITY_FORCE);

		JPanel pnlMotionSensingTracking = new JPanel();
		pnlMotionSensingTracking.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		this.sbMotionSensingTracking = new JYSwitchButton("", true);
		this.sbMotionSensingTracking.setFont(Themes.Fuente.DEFAULT_TEXT);
		this.sbMotionSensingTracking.addItemListener(new ItemListener() {

			@Override
			public void itemStateChanged(ItemEvent e) {
				MainFrame.this.sbMotionSensingTracking.setText(Constants.Texts.MOTION_SENSING_TRACKING + " " + (MainFrame.this.sbMotionSensingTracking.isSelected() ? Constants.Texts.WAS_STARTED : Constants.Texts.WAS_STOPPED));
				MainFrame.this.sbMotionSensingTracking.setForeground(MainFrame.this.sbMotionSensingTracking.isSelected() ? Themes.Colore.LABEL_MOTION_SENSING_TRACKING_WAS_STARTED_FG : Themes.Colore.LABEL_MOTION_SENSING_TRACKING_WAS_STOPPED_FG);
				MainFrame.this.wiiusej.setMotionSensingTracking(MainFrame.this.sbMotionSensingTracking.isSelected());
			}
		});
		this.sbMotionSensingTracking.setSelected(false);
		this.sbMotionSensingTracking.setEnabled(false);
		UIUtils.addComponent(pnlMotionSensingTracking, new JLabel(""), 1, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 5, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(pnlMotionSensingTracking, this.sbMotionSensingTracking, 1, 1, 0, 0, GridBagConstraints.NONE, 5, 0, 5, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(pnlMotionSensingTracking, new JLabel(""), GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 5, GridBagConstraints.CENTER);

		this.trainingMonitorPanel = new JPanel();
		this.trainingMonitorPanel.setBackground(Themes.Colore.TRAINING_MONITOR_PANEL_BG);

		JPanel pnlStatus = new JPanel();
		pnlStatus.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		this.lblTrainingMonitorStatus = new JLabel("");
		this.lblTrainingMonitorStatus.setHorizontalAlignment(JLabel.TRAILING);
		this.lblTrainingMonitorStatus.setOpaque(true);
		this.lblTrainingMonitorStatus.setFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		this.lblTrainingMonitorStatus.setForeground(Themes.Colore.TRAINING_MONITOR_STATUS_FG);
		this.lblTrainingMonitorStatus.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		this.lblTrainingMonitorStatus.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 5));
		this.lblTrainingCountText = new JLabel(Constants.Texts.TRAINING_COUNT);
		this.lblTrainingCountText.setHorizontalAlignment(JLabel.LEADING);
		this.lblTrainingCountText.setFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		this.lblTrainingCountText.setForeground(Themes.Colore.TRAINING_MONITOR_COUNT_TEXT_FG);
		this.lblTrainingCountText.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 0));
		this.lblTrainingCountText.addMouseListener(this.handler);
		this.lblTrainingCount = new JLabel("0");
		this.lblTrainingCount.setHorizontalAlignment(JLabel.LEADING);
		this.lblTrainingCount.setFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
		this.lblTrainingCount.setForeground(Themes.Colore.TRAINING_MONITOR_COUNT_NUMBER_FG);
		this.lblTrainingCount.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 0));
		this.lblTrainingCount.addMouseListener(this.handler);

		UIUtils.addComponent(pnlStatus, this.lblTrainingCountText, 1, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.LINE_START);
		UIUtils.addComponent(pnlStatus, this.lblTrainingCount, 1, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.LINE_START);
		UIUtils.addComponent(pnlStatus, new JLabel(""), 1, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(pnlStatus, this.lblTrainingMonitorStatus, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.LINE_END);

		JPanel leftPanel = new JPanel();
		UIUtils.addComponent(leftPanel, tabbedPane, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(leftPanel, pnlMotionSensingTracking, GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(leftPanel, new JScrollPane(this.trainingMonitorPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), GridBagConstraints.REMAINDER, 1, 1, 2, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(leftPanel, pnlStatus, GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 0, 0, 0, 0, GridBagConstraints.CENTER);

		JPanel rightPanel = new JPanel();
		rightPanel.setBackground(Themes.Colore.CONTENT_PANEL_BG);
		ButtonBar bb = new ButtonBar();
		this.btnConnect = UIUtils.createButton(Constants.Texts.CONNECT, true, true);
		this.btnConnect.setForeground(Themes.Colore.CONNECT_BUTTON_FG);
		this.btnConnect.addActionListener(this.handler);
		bb.add(this.btnConnect);
		this.btnDisconnect = UIUtils.createButton(Constants.Texts.DISCONNECT, true, true);
		this.btnDisconnect.setForeground(Themes.Colore.DISCONNECT_BUTTON_FG);
		this.btnDisconnect.addActionListener(this.handler);
		bb.add(this.btnDisconnect);
		this.btnGroup = new ButtonGroup();
		this.btnGroup.add(this.btnConnect);
		this.btnGroup.add(this.btnDisconnect);
		this.btnDisconnect.setSelected(true);
		this.wiimotePanel = new WiimotePanel();
		UIUtils.addComponent(rightPanel, bb, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 0, 15, 10, 15, GridBagConstraints.CENTER);
		UIUtils.addComponent(rightPanel, this.wiimotePanel, GridBagConstraints.REMAINDER, 1, 0, 0, GridBagConstraints.NONE, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(rightPanel, new JLabel(""), GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);

		UIUtils.addComponent(this.trainingPanel, leftPanel, GridBagConstraints.RELATIVE, 1, 1, 1, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);
		UIUtils.addComponent(this.trainingPanel, rightPanel, GridBagConstraints.REMAINDER, 1, 0, 1, GridBagConstraints.VERTICAL, 0, 0, 0, 0, GridBagConstraints.CENTER);
	}

	public void initUIComponents() {
		createNavigationPanel();
		createContentPanel();

		createTrainingPanel();
		createGestureRecognitionPanel();
		createGestureModelsPanel();

		UIUtils.addComponent(getContentPane(), this.navigationPanel, GridBagConstraints.RELATIVE, 1, 0, 1, GridBagConstraints.VERTICAL, 0, 0, 0, 0, GridBagConstraints.LINE_START);
		UIUtils.addComponent(getContentPane(), this.contentTitledPanel, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.BOTH, 0, 0, 0, 0, GridBagConstraints.CENTER);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle(Constants.APPLICATION_TITLE);
		setIconImage(Constants.Images.APP_ICON.getImage());
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(getGraphicsConfiguration());
		int taskBarHeight = screenInsets.bottom;
		setSize(screenSize.width, screenSize.height - taskBarHeight);
		setLocationRelativeTo(null);
		setVisible(false);
	}

	public void switchContent(short type) {
		for (ContentType contentType : ContentType.values()) {
			if (contentType.getValue() == type) {
				switchContent(contentType);
				break;
			}
		}
	}

	public void switchContent(ContentType type) {
		if (this.currentContentType == type) {
			return;
		}
		this.currentContentType = type;
		JComponent newContent = null;
		switch (type) {
		case TRAINING:
			this.btnTraining.requestFocus();
			this.contentTitledPanel.setTitle(Constants.Texts.TRAINING);
			newContent = this.trainingPanel;
			break;

		case GESTURE_RECOGNITION:
			this.btnGesture.requestFocus();
			this.contentTitledPanel.setTitle(Constants.Texts.GESTURE_RECOGNITION);
			newContent = this.gestureRecognitionPanel;
			break;

		case GESTURE_MODELS:
			this.btnLibrary.requestFocus();
			this.contentTitledPanel.setTitle(Constants.Texts.GESTURE_MODELS);
			newContent = this.gestureModelsPanel;
			break;

		default:
			break;
		}
		this.contentPanel.removeAll();
		this.contentPanel.add(newContent, BorderLayout.CENTER);
		validate();
		repaint();
	}

	public void updateTrainingMonitorPanel(DetailedInfo detailedInfo) {
		DetailedInfoPanel detailedInfoPanel = new DetailedInfoPanel(detailedInfo);
		UIUtils.addComponent(this.trainingMonitorPanel, detailedInfoPanel, GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.HORIZONTAL, 5, 5, 5, 5, GridBagConstraints.CENTER);
		validate();
		repaint();
	}

	public void updateTrainingCount(Object count) {
		this.lblTrainingCount.setText(String.valueOf(count));
	}

	public void updateGestureRecognitionStatus(String status) {
		this.lblGestureRecognition.setForeground(this.lblGestureRecognition.getForeground().equals(Themes.Colore.TRAINING_MONITOR_STATUS_FG) ? Themes.Colore.TRAINING_MONITOR_COUNT_NUMBER_FG : Themes.Colore.TRAINING_MONITOR_STATUS_FG);
		this.lblGestureRecognition.setText(status);
	}

	public void updateTrainingMonitorStatus(Object status) {
		updateTrainingMonitorStatus(status, false);
	}

	public void updateTrainingMonitorStatus(Object status, boolean isAppended) {
		this.lblTrainingMonitorStatus.setText((isAppended ? this.lblTrainingMonitorStatus.getText() : "") + String.valueOf(status));
	}

	public void updateGestureModelsList(GestureModel gestureModel, int numGesturesWasUsedForTraining) {
		updateGestureModelsList(gestureModel, numGesturesWasUsedForTraining, null);
	}

	public void updateGestureModelsList(GestureModel gestureModel, int numGesturesWasUsedForTraining, String displayName) {
		displayName = (displayName == null ? Constants.Texts.GESTURE_MODEL + "-" + this.hmapGestureModels.size() : displayName);
		this.gestureModelsListModel.addElement(displayName);
		this.hmapGestureModels.put(displayName, new GestureModelInfo(numGesturesWasUsedForTraining, gestureModel));
		updateGestureModelCount(this.hmapGestureModels.size());
	}

	public String getGestureModelDisplayName(int index) {
		return this.gestureModelsListModel.get(index);
	}

	public void updateGestureModelCount(Object count) {
		this.lblGestureModelCount.setText(String.valueOf(count));
	}

	private void connectWiimote() {
		if (!this.wiiusej.connectWiimote() && this.wiiusej.isFirstConnect()) {
			this.btnGroup.clearSelection();
			JXErrorPane.showDialog(this, new ErrorInfo(Constants.Messages.WARNING_DIALOG_TITLE, Constants.Messages.WARNING_CANNOT_CONNECT_TO_DEVICE_BASIC, Constants.Messages.WARNING_CANNOT_CONNECT_TO_DEVICE_DETAILED, "", null, Level.WARNING, null));
			return;
		}

		if (MainFrame.this.btnConnect.isSelected()) {
			MainFrame.this.btnConnect.setText(Constants.Texts.RECONNECT);
			MainFrame.this.btnConnect.setForeground(Themes.Colore.RECONNECT_BUTTON_FG);
		}
		this.sbMotionSensingTracking.setEnabled(true);
		clearViews();
		this.wiimotePanel.setCurrentImg(Constants.Images.WIIMOTE);
	}

	private void disconnectWiimote() {
		this.wiiusej.disconnectWiimote();

		MainFrame.this.btnConnect.setText(Constants.Texts.CONNECT);
		MainFrame.this.btnConnect.setForeground(Themes.Colore.CONNECT_BUTTON_FG);
		this.sbMotionSensingTracking.setSelected(false);
		this.sbMotionSensingTracking.setEnabled(false);
		clearViews();
		updateTrainingCount("0");
		updateTrainingMonitorStatus("");
		this.wiimotePanel.setCurrentImg(Constants.Images.WIIMOTE_DISABLED);
	}

	private void clearViews() {
		this.accelerationPanel.clearView();
		this.orientationPanel.clearView();
		this.gforcePanel.clearView();
		clearTrainingMonitorPanel();
	}

	public void clearTrainingMonitorPanel() {
		this.trainingMonitorPanel.removeAll();
		validate();
		repaint();
	}

	private void changeGestureModelDisplayName() {
		String selectedItem = this.listGestureModels.getSelectedValue();
		String newName = JOptionPane.showInputDialog(this, Constants.Messages.CHANGE_GESTURE_MODEL_DISPLAY_NAME + " " + selectedItem, Constants.Messages.CHANGE_GESTURE_MODEL_DISPLAY_NAME_DIALOG_TITLE, JOptionPane.OK_CANCEL_OPTION);
		if (newName.length() > 0) {
			int selectedIndex = this.listGestureModels.getSelectedIndex();
			this.gestureModelsListModel.setElementAt(newName, selectedIndex);
			GestureModelInfo gestureModelInfo = this.hmapGestureModels.remove(selectedItem);
			this.hmapGestureModels.put(newName, gestureModelInfo);
			this.listGestureModels.clearSelection();
			this.listGestureModels.setSelectedIndex(selectedIndex);
		}
	}

	private void loadGestureModel() {
		JFileChooser fc = new JFileChooser();

		int retVal = fc.showOpenDialog(this);
		if (retVal == JFileChooser.APPROVE_OPTION) {
			File f = fc.getSelectedFile();
			String gestureModelName = FilenameUtils.removeExtension(f.getName());
			this.wiigee.getWiimote().loadGesture(f.getParent() + "/" + gestureModelName);
			this.wiigee.loadGesture(f.getParent() + "/" + gestureModelName);
			this.gestureModelsListModel.addElement(gestureModelName);
			this.hmapGestureModels.put(gestureModelName, new GestureModelInfo(this.wiigee.getGestureModels().lastElement()));
			updateGestureModelCount(this.hmapGestureModels.size());
		}
	}

	private void saveGestureModel() {
		File f = null;
		JFileChooser fc = new JFileChooser();
		fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

		int retVal = fc.showSaveDialog(this);
		if (retVal == JFileChooser.APPROVE_OPTION) {
			f = fc.getSelectedFile();
			int selectedGestureModelID = this.listGestureModels.getSelectedIndex();
			this.wiigee.getWiimote().saveGesture(selectedGestureModelID, f.getPath() + "/" + this.gestureModelsListModel.elementAt(selectedGestureModelID));
		}
	}

	class EventsHandler implements ActionListener, MouseListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if (e.getSource().equals(MainFrame.this.btnTraining)) {
				switchContent(ContentType.TRAINING);
			} else if (e.getSource().equals(MainFrame.this.btnGesture)) {
				switchContent(ContentType.GESTURE_RECOGNITION);
			} else if (e.getSource().equals(MainFrame.this.btnLibrary)) {
				switchContent(ContentType.GESTURE_MODELS);
			} else if (e.getSource().equals(MainFrame.this.btnConnect)) {
				connectWiimote();
			} else if (e.getSource().equals(MainFrame.this.btnDisconnect)) {
				disconnectWiimote();
			} else if (e.getSource().equals(MainFrame.this.btnEditGestureModelDisplayName)) {
				if (MainFrame.this.listGestureModels.getSelectedIndex() == -1) {
					JOptionPane.showMessageDialog(MainFrame.this, Constants.Messages.PLEASE_SELECT_AT_LEAST_ONE_ITEM_FIRST, Constants.Messages.WARNING_DIALOG_TITLE, JOptionPane.WARNING_MESSAGE);
					return;
				}
				changeGestureModelDisplayName();
			} else if (e.getSource().equals(MainFrame.this.btnLoadGestureModel)) {
				loadGestureModel();
			} else if (e.getSource().equals(MainFrame.this.btnSaveGestureModel)) {
				if (MainFrame.this.listGestureModels.getSelectedIndex() == -1) {
					JOptionPane.showMessageDialog(MainFrame.this, Constants.Messages.PLEASE_SELECT_AT_LEAST_ONE_ITEM_FIRST, Constants.Messages.WARNING_DIALOG_TITLE, JOptionPane.WARNING_MESSAGE);
					return;
				}
				saveGestureModel();
			}
		}

		@Override
		public void mouseClicked(MouseEvent e) {

		}

		@Override
		public void mousePressed(MouseEvent e) {

		}

		@Override
		public void mouseReleased(MouseEvent e) {
			if (e.getSource().equals(MainFrame.this.lblTrainingCountText) || e.getSource().equals(MainFrame.this.lblTrainingCount)) {
				e.consume();

				Vector<Gesture> gestures = MainFrame.this.wiigee.getRecoredTrainingData();

				JDialog dialog = new JDialog();

				final JXTitledPanel recordedTrainingInfoTitledPanel = new JXTitledPanel();
				recordedTrainingInfoTitledPanel.setTitleFont(Themes.Fuente.DEFAULT_TEXT_BOLD);
				recordedTrainingInfoTitledPanel.setTitleForeground(Themes.Colore.CONTENT_PANEL_TITLE_FG);
				recordedTrainingInfoTitledPanel.setTitlePainter(new MattePainter(new GradientPaint(0, 0, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_1, 140, 140, Themes.Colore.TITLED_PANEL_GRADIENT_COLOR_2, true)));
				recordedTrainingInfoTitledPanel.setBorder(null);
				final JPanel recordedTrainingInfoPanel = new JPanel();
				recordedTrainingInfoPanel.setBackground(Themes.Colore.CONTENT_PANEL_BG);
				recordedTrainingInfoPanel.setLayout(new BorderLayout());
				recordedTrainingInfoTitledPanel.setContentContainer(new JScrollPane(recordedTrainingInfoPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));

				final HashMap<String, Gesture> hmapRecordedTraining = new HashMap<String, Gesture>();
				final DefaultListModel<String> listModel = new DefaultListModel<String>();
				for (int i = 0; i < gestures.size(); i++) {
					String itemName = Constants.Texts.TRAINED + "-" + i;
					listModel.addElement(itemName);
					hmapRecordedTraining.put(itemName, gestures.get(i));
				}
				final JList<String> listRecordedTraining = new JList<String>(listModel);
				listRecordedTraining.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
				listRecordedTraining.addListSelectionListener(new ListSelectionListener() {

					@Override
					public void valueChanged(ListSelectionEvent e) {
						if (!e.getValueIsAdjusting()) {
							int selectedIndex = -1;
							if ((selectedIndex = listRecordedTraining.getSelectedIndex()) == -1) {
								return;
							}

							recordedTrainingInfoTitledPanel.setTitle(listModel.getElementAt(selectedIndex) + " > " + Constants.Texts.GESTURE);

							recordedTrainingInfoPanel.removeAll();
							recordedTrainingInfoPanel.add(new GestureInfoPanel(hmapRecordedTraining.get(listModel.getElementAt(selectedIndex))), BorderLayout.CENTER);
							recordedTrainingInfoPanel.validate();
							recordedTrainingInfoPanel.repaint();
						}
					}
				});
				listRecordedTraining.setPreferredSize(new Dimension(240, listRecordedTraining.getPreferredSize().height));
				JScrollPane scrollPane = new JScrollPane(listRecordedTraining, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
				scrollPane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER), BorderFactory.createMatteBorder(5, 2, 5, 2, Themes.Colore.CONTENT_PANEL_BG)), BorderFactory.createLineBorder(Themes.Colore.DETAILED_INFO_PANEL_BORDER)));

				dialog.getContentPane().add(scrollPane, BorderLayout.WEST);
				dialog.getContentPane().add(recordedTrainingInfoTitledPanel, BorderLayout.CENTER);

				dialog.setModal(true);
				dialog.setModalityType(ModalityType.APPLICATION_MODAL);
				dialog.setTitle(Constants.Texts.RECORDED_TRAINING_INFO_PANEL_TITLE);
				dialog.setSize(960, 640);
				dialog.setLocationRelativeTo(null);
				dialog.setVisible(true);
			}
		}

		@Override
		public void mouseEntered(MouseEvent e) {

		}

		@Override
		public void mouseExited(MouseEvent e) {

		}
	}
}
